package com.loklok.code.confuse.util;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.loklok.code.confuse.constant.Constants;

import java.util.concurrent.Callable;

public class ApiUtils {

    public static boolean isRestfulApiMethod(PsiMethod psiMethod) {
        return ApplicationManager.getApplication().runReadAction((Computable<Boolean>) () -> {
            for (PsiAnnotation annotation : psiMethod.getAnnotations()) {
                String packagePath = annotation.getQualifiedName();
                if (Constants.RequestMapping.equals(packagePath) ||
                        Constants.ShortRequestMapping.equals(packagePath) ||
                        Constants.GetMapping.equals(packagePath) ||
                        Constants.ShortGetMapping.equals(packagePath) ||
                        Constants.PostMapping.equals(packagePath) ||
                        Constants.ShortPostMapping.equals(packagePath) ||
                        Constants.PutMapping.equals(packagePath) ||
                        Constants.ShortPutMapping.equals(packagePath) ||
                        Constants.DeleteMapping.equals(packagePath) ||
                        Constants.ShortDeleteMapping.equals(packagePath) ||
                        Constants.PatchMapping.equals(packagePath) ||
                        Constants.ShortPatchMapping.equals(packagePath)) {
                    return true;
                }
            }
            return false;
        });
    }


    public static boolean isMappingAnnotation(PsiAnnotation psiAnnotation) {
        return ApplicationManager.getApplication().runReadAction((Computable<Boolean>) () -> {
            String qualifiedName = psiAnnotation.getQualifiedName();
            return Constants.RequestMapping.equals(qualifiedName) ||
                    Constants.GetMapping.equals(qualifiedName) ||
                    Constants.PostMapping.equals(qualifiedName) ||
                    Constants.PutMapping.equals(qualifiedName) ||
                    Constants.DeleteMapping.equals(qualifiedName) ||
                    Constants.PatchMapping.equals(qualifiedName);
        });
    }


    public static String getPath(PsiMethod psiMethod) {
        return ApplicationManager.getApplication().runReadAction((Computable<String>) () -> {
            StringBuilder result = new StringBuilder();
            PsiClass psiClass = PsiTreeUtil.getParentOfType(psiMethod, PsiClass.class);
            if (psiClass == null) {
                return "";
            }
            PsiAnnotation classAnnotation = psiClass.getAnnotation(Constants.RequestMapping);
            // 拼接 类上面 RequestMapping 注解的路径
            if (classAnnotation != null) {
                result.append(getAnnotationAttributeValue(classAnnotation, "value"));
            }
            for (PsiAnnotation annotation : psiMethod.getAnnotations()) {
                if (isMappingAnnotation(annotation)) {
                    result.append(getAnnotationAttributeValue(annotation, "value"));
                    break;
                }
            }
            return result.toString();
        });
    }


    public static String getDesc(PsiMethod psiMethod) {
        if (psiMethod.getDocComment() == null) {
            return "";
        }
        return psiMethod.getDocComment().getText();
    }

    public static String getAnnotationAttributeValue(PsiAnnotation annotation, String attrName) {
        return ApplicationManager.getApplication().runReadAction((Computable<String>) () -> {
            PsiNameValuePair[] attrs = annotation.getParameterList().getAttributes();
            for (PsiNameValuePair attr : attrs) {
                if (attr.getAttributeName().equals(attrName)) {
                    return attr.getLiteralValue();
                }
            }
            return "";
        });
    }


    public static String getHTTPMethod(PsiMethod psiMethod) {
        // 通过 psiMethod的 getAnnotation 方法，判断注解上是否有 GetMapping
        // 如果有，表示 HTTP 请求方法为 Get 请求，以此类推
        if (psiMethod.getAnnotation(Constants.GetMapping) != null) {
            return "GET";
        } else if (psiMethod.getAnnotation(Constants.PostMapping) != null) {
            return "POST";
        } else if (psiMethod.getAnnotation(Constants.DeleteMapping) != null) {
            return "DELETE";
        } else if (psiMethod.getAnnotation(Constants.PutMapping) != null) {
            return "PUT";
        } else if (psiMethod.getAnnotation(Constants.PatchMapping) != null) {
            return "PATCH";
        }
        return "";
    }



    private static PsiClass getPsiClassByType(PsiType returnType, Project project) {
        // JavaPsiFacade.findClass() 方法在 PSI 中非常重要
        // 可通过类路径，获取到类的 PsiClass 对象
        return JavaPsiFacade.getInstance(project).findClass(returnType.getCanonicalText(), GlobalSearchScope.allScope(project));
    }


}
